import select, sys, threading

class CubeConnection(threading.Thread):
	def __init__(self, cube, servers):
		threading.Thread.__init__(self)
		self.daemon = True
		
		self.cube = cube
		self.servers = servers
		
		self.poll = select.poll()
		for server in self.servers:
			self.poll.register(server.get_fd(), select.POLLIN)
		
		self.accept()
		self.start()
	
	def accept(self):
		try:
			for fd, state in self.poll.poll():
				for server in self.servers:
					if server.get_fd() == fd:
						self.client = server.accept()
						self.client.send("%c%c%c\r\n" % (self.cube.width, self.cube.depth, self.cube.height))
						return
		except (KeyboardInterrupt, select.error):
			sys.exit(0)
	
	def feedUntil(self, char):
		data = ""
		while True:
			byte = self.recv(1)
			if byte == char:
				return data
			data += byte
	
	def recv(self, *args):
		data = self.client.recv(*args)
		if data == "":
			raise EOFError
		sys.stdout.write(data)
		return data
	
	def reset(self):
		print "Connection closed, resetting cube..."
		lock = threading.Lock()
		lock.acquire()
		
		def reset(cube):
			for i in range(cube.height):
				for j in range(cube.depth):
					for k in range(cube.width):
						cube.setEnabled(j, k, i, False)
			
			print "Cube resetted."
			
			self.accept()
			lock.release()
		
		self.cube.addJob(reset)
		lock.acquire()
		lock.release()
	
	def run(self):
		while True:
			try:
				self.read()
			except EOFError:
				self.reset()
				continue
	
	def read(self):
		data = self.recv(1)
		
		if data.lower() == "l":
			layer = 0
			row = 0
			column = 0
			try:
				layer = int(self.feedUntil(","))
			except Exception,e:
				return
			
			while True:
				char = self.recv(1)
				if char == "0":
					self.setEnabled(column, row, layer, False)
				elif char == "1":
					self.setEnabled(column, row, layer, True)
				else:
					break
				
				column += 1
				if column >= self.cube.width:
					column = 0
					row += 1
					if row >= self.cube.depth:
						row = 0
			
			return
		
		if data.lower() == "s":
			layer  = ord(self.recv(1))
			row    = ord(self.recv(1))
			column = ord(self.recv(1))
			
			char = ord(self.recv(1))
			if char == 0:
				self.setEnabled(column, row, layer, False)
			elif char == 1:
				self.setEnabled(column, row, layer, True)
			return
		
	
	def setEnabled(self, x,y,z, enabled):
		self.cube.addJob(lambda cube: cube.setEnabled(x,y,z,enabled))
	

